package com.atguigu.java.ai.langchain4j.tools;

import com.atguigu.java.ai.langchain4j.entity.dto.Appointment;
import com.atguigu.java.ai.langchain4j.entity.dto.LockNumber;
import com.atguigu.java.ai.langchain4j.entity.po.Doctor;
import com.atguigu.java.ai.langchain4j.entity.po.LockedRegistration;
import com.atguigu.java.ai.langchain4j.service.DoctorService;
import com.atguigu.java.ai.langchain4j.service.LockedRegistrationService;
import com.atguigu.java.ai.langchain4j.utils.Result;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.UUID;

/**
 * @author zhaoyf
 * @version 1.0
 * @description 预约挂号tools
 * @date 2025/8/2 0:48
 */
@Component
@RequiredArgsConstructor
public class AppointmentRegisterTools {

    private final DoctorService doctorService;
    private final LockedRegistrationService lockedRegistrationService;

    @Tool(name="预约挂号", value = "根据参数，先执行工具方法queryDepartment查询是否可预约，并直接给用户回答是否可预约，并让用户确认所有预约信息，用户确认后再进行预约。")
    public String bookAppointment(LockNumber LockNumber){
        //查找数据库中是否包含对应的预约记录
        LambdaQueryWrapper<LockedRegistration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LockedRegistration::getDeptName, LockNumber.getDeptName());
        queryWrapper.eq(LockedRegistration::getDate, LockNumber.getDate());
        queryWrapper.eq(LockedRegistration::getTimeSlot, LockNumber.getTimeSlot());
        queryWrapper.eq(LockedRegistration::getIdCard, LockNumber.getIdCard());
        LockedRegistration result = lockedRegistrationService.getOne(queryWrapper);
        if (result != null) {
            return "您在相同的科室和时间已有预约";
        }
        //若同一病人不存在预约记录，则进行预约
        // 获取科室和医生id
        LambdaQueryWrapper<Doctor> docWrapper = new LambdaQueryWrapper<>();
        docWrapper.eq(Doctor::getDeptName, LockNumber.getDeptName());
        docWrapper.eq(Doctor::getDoctorName, LockNumber.getDoctorName());
        docWrapper.eq(Doctor::getScheduleDate, LockNumber.getDate());
        Doctor doctor = doctorService.getOne(docWrapper);
        // 创建锁号记录
        LockedRegistration lockedRegistration = LockedRegistration.builder()
                .lockId(null)//防止大模型幻觉设置了id
                .deptName(LockNumber.getDeptName())
                .deptId(doctor.getDeptId())
                .doctorName(LockNumber.getDoctorName())
                .doctorId(doctor.getDoctorId())
                .date(LockNumber.getDate())
                .timeSlot(LockNumber.getTimeSlot())
                .slotId(UUID.randomUUID().toString())
                .idCard(LockNumber.getIdCard())
                .patientName(LockNumber.getPatientName())
                .build();
        // 保存锁号记录
        boolean save = lockedRegistrationService.save(lockedRegistration);
        return save? "预约锁号成功，请返回我的挂号记录里面进行支付挂号，若5分钟内未支付将自动取消预约记录！" :"预约失败，请稍后重试！";
    }

    @Tool(name="取消预约挂号", value = "根据参数，查询预约是否存在，如果存在则删除预约记录并返回取消预约成功，否则返回取消预约失败")
    public String cancelAppointment(LockNumber LockNumber){
        //查找数据库中是否包含对应的预约记录
        LambdaQueryWrapper<LockedRegistration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LockedRegistration::getDeptName, LockNumber.getDeptName());
        queryWrapper.eq(LockedRegistration::getDate, LockNumber.getDate());
        queryWrapper.eq(LockedRegistration::getTimeSlot, LockNumber.getTimeSlot());
        queryWrapper.eq(LockedRegistration::getIdCard, LockNumber.getIdCard());
        LockedRegistration result = lockedRegistrationService.getOne(queryWrapper);
        if (result != null){
            //删除预约记录
           if(lockedRegistrationService.removeById(result.getLockId())){
                return "取消预约锁号成功";
            }else{
               return "取消预约失败";
            }
        }
        // 没有预约记录
        return "您没有预约记录，请核对预约科室和时间";
    }

    /**
     * 查询是否有号源数据
     * @param deptName  科室名称
     * @param date      预约日期
     * @param timeSlot  时间段
     * @param doctorName 医生姓名
     */
    @Tool(name = "查询是否有号源", value="根据科室名称，日期，时间和医生查询是否有号源，并返回给用户")
    public boolean queryDepartment(
            @P(value = "科室名称") String deptName,
            @P(value = "日期") String date,
            @P(value = "时间，可选值：上午、下午") String timeSlot,
            @P(value = "医生名称") String doctorName
    ) {
        System.out.println("---------------------");
        //如果指定了医生名字，则判断医生是否有排班（没有排班返回false）
        if(!StringUtils.isEmpty(doctorName)){
            Result result = doctorService.queryNumberSource(date, deptName, doctorName);
           return result.isSuccess();
        }else{//如果没有指定医生名字，则根据其他条件查询是否有可以预约的医生（有返回true，否则返回false）；
            Result result = doctorService.queryNumberSourceWithoutDoctor(date, deptName);
            return result.isSuccess();
        }
    }
}
